with v8.Class_Primitive, v8.Class_Value;
with v8.Class_External_String_Resource, v8.Class_External_Ascii_String_Resource;
package v8.Class_String is
   type String (<>) is new v8.Class_Primitive.Primitive with private;
   type Pointer is access all v8.Class_String.String;
   -- A JavaScript string value (ECMA-262, 4.3.17).

   function Length (this : String) return int;
   -- Returns the number of characters in this string.

   function Utf8_Length (this : String) return int;
   -- Returns the number of bytes in the UTF-8 encoded
   -- representation of this string.

   -- Write the contents of the string to an external buffer.
   -- If no arguments are given, expects the buffer to be large
   -- enough to hold the entire string and NULL terminator. Copies
   -- the contents of the string and the NULL terminator into the
   -- buffer.
   --
   -- WriteUtf8 will not write partial UTF-8 sequences, preferring to stop
   -- before the end of the buffer.
   --
   -- Copies up to length characters into the output buffer.
   -- Only null-terminates if there is enough space in the buffer.
   --
   -- \param buffer The buffer into which the string will be copied.
   -- \param start The starting position within the string at which
   -- copying begins.
   -- \param length The number of characters to copy from the string.  For
   --    WriteUtf8 the number of bytes in the buffer.
   -- \param nchars_ref The number of characters written, can be NULL.
   -- \param hints Various hints that might affect performance of this or
   --    subsequent operations.
   -- \return The number of characters copied to the buffer excluding the null
   --    terminator.  For WriteUtf8: The number of bytes copied to the buffer
   --    including the null terminator.
   function Write
     (this   : String;
      buffer : access uint16_t;
      start  : int := 0;
      length : int := -1;
      hints  : String_Write_Hints.Enum := String_Write_Hints.NO_HINTS
     ) return int;
   function Write_Ascii
     (this   : String;
      buffer : access char;
      start  : int := 0;
      length : int := -1;
      hints  : String_Write_Hints.Enum := String_Write_Hints.NO_HINTS
     ) return int;
   function Write_Utf8
     (this       : String;
      buffer     : access char;
      length     : int := -1;
      nchars_ref : access int := null;
      hints      : String_Write_Hints.Enum := String_Write_Hints.NO_HINTS
     ) return int;

   function Empty return Pointer;  -- Local<String>
   -- A zero length string.

   function Is_External (this : String) return bool;
   -- Returns true if the string is external

   function Is_External_Ascii (this : String) return bool;
   -- Returns true if the string is both external and ascii

   function Get_External_String_Resource
     (this : String
     ) return v8.Class_External_String_Resource.Pointer;
   -- Get the ExternalStringResource for an external string.  Returns
   -- NULL if IsExternal() doesn't return true.

   function Get_External_Ascii_String_Resource
     (this : String
     ) return v8.Class_External_Ascii_String_Resource.Pointer;
   -- Get the ExternalAsciiStringResource for an external ascii string.
   -- Returns NULL if IsExternalAscii() doesn't return true.

   function Create (S : Standard.String) return Pointer;
   -- Allocates a new string from either utf-8 encoded or ascii data.

   function Create (S : Wide_String) return Pointer;
   -- Allocates a new string from utf16 data.

   function New_Symbol (S : Standard.String) return Pointer;
   -- Creates a symbol. Returns one if it exists already.

   function "&" (left : Pointer; right : Pointer) return Pointer;
   -- Creates a new string by concatenating the left and the right strings
   -- passed in as parameters.

   function New_External
     (resource : v8.Class_External_String_Resource.Pointer
     ) return Pointer;
   -- Creates a new external string using the data defined in the given
   -- resource. When the external string is no longer live on V8's heap the
   -- resource will be disposed by calling its Dispose method. The caller of
   -- this function should not otherwise delete or modify the resource. Neither
   -- should the underlying buffer be deallocated or modified except through the
   -- destructor of the external string resource.

   function Make_External
     (this     : in out String;
      resource : v8.Class_External_String_Resource.Pointer
     ) return Pointer;
   -- Associate an external string resource with this string by transforming it
   -- in place so that existing references to this string in the JavaScript heap
   -- will use the external string resource. The external string resource's
   -- character contents need to be equivalent to this string.
   -- Returns true if the string has been changed to be an external string.
   -- The string is not modified if the operation fails. See NewExternal for
   -- information on the lifetime of the resource.

   function New_External_Ascii
     (resource : v8.Class_External_Ascii_String_Resource.Pointer
     ) return Pointer;
   -- Creates a new external string using the ascii data defined in the given
   -- resource. When the external string is no longer live on V8's heap the
   -- resource will be disposed by calling its Dispose method. The caller of
   -- this function should not otherwise delete or modify the resource. Neither
   -- should the underlying buffer be deallocated or modified except through the
   -- destructor of the external string resource.

   function Make_External_Ascii
     (this     : in out String;
      resource : v8.Class_External_Ascii_String_Resource.Pointer
     ) return bool;
   -- Associate an external string resource with this string by transforming it
   -- in place so that existing references to this string in the JavaScript heap
   -- will use the external string resource. The external string resource's
   -- character contents need to be equivalent to this string.
   -- Returns true if the string has been changed to be an external string.
   -- The string is not modified if the operation fails. See NewExternal for
   -- information on the lifetime of the resource.

   function Can_Make_External (this : in out String) return bool;
   -- Returns true if this string can be made external.

   function New_Undetectable (S : Standard.String) return Pointer;
   -- Creates an undetectable string from the supplied ascii or utf-8 data.

   function New_Undetectable_Utf16 (S : Wide_String) return Pointer;
   -- Creates an undetectable string from the supplied utf-16 data.

   function Slice
     (this   : String;
      From   : Positive := 1;
      Length : Integer := -1
     ) return Standard.Wide_String;
   -- helper function to get string content as ada wide_string

   function Cast is new Ada.Unchecked_Conversion (v8.Class_Value.Pointer, Pointer);
   -- Convert Value to String

private
   type String is new v8.Class_Primitive.Primitive with null record;

   pragma Import (CPP, Length, "_ZNK2v86String6LengthEv");
   pragma Import (CPP, Utf8_Length, "_ZNK2v86String10Utf8LengthEv");
   pragma Import (CPP, Write, "_ZNK2v86String5WriteEPtiiNS0_10WriteHintsE");
   pragma Import (CPP, Write_Ascii, "_ZNK2v86String10WriteAsciiEPciiNS0_10WriteHintsE");
   pragma Import (CPP, Write_Utf8, "_ZNK2v86String9WriteUtf8EPciPiNS0_10WriteHintsE");
   pragma Import (CPP, Empty, "_ZN2v86String5EmptyEv");
   pragma Import (CPP, Is_External, "_ZNK2v86String10IsExternalEv");
   pragma Import (CPP, Is_External_Ascii, "_ZNK2v86String15IsExternalAsciiEv");
   pragma Import (CPP, Get_External_String_Resource, "_Z25GetExternalStringResourcePN2v86StringE");
   pragma Import (CPP, Get_External_Ascii_String_Resource, "_ZNK2v86String30GetExternalAsciiStringResourceEv");
   pragma Import (CPP, "&", "_ZN2v86String6ConcatENS_6HandleIS0_EES2_");
   pragma Import (CPP, New_External, "_ZN2v86String11NewExternalEPNS0_22ExternalStringResourceE");
   pragma Import (CPP, Make_External, "_ZN2v86String12MakeExternalEPNS0_22ExternalStringResourceE");
   pragma Import (CPP, New_External_Ascii, "_ZN2v86String11NewExternalEPNS0_27ExternalAsciiStringResourceE");
   pragma Import (CPP, Make_External_Ascii, "_ZN2v86String12MakeExternalEPNS0_27ExternalAsciiStringResourceE");
   pragma Import (CPP, Can_Make_External, "_ZN2v86String15CanMakeExternalEv");

end v8.Class_String;
